package worldLogic;

import javax.imageio.ImageIO;
import java.util.HashMap;
import java.util.Vector;
import java.io.*;
import java.awt.*;
import java.net.URL;

public class Map {

    private HashMap<Coordinate, Vector<PhysicalObject>> mapData;

    //Changing the numerical order of these will screw getObjectsInRadius up
    //E.g. Must be smell > talk > sight > collision
    private Integer smellRadius = 20;
    private Integer talkRadius = 14;
    private Integer sightRadius = 10;
    private Integer collisionRadius = 1;

    private Image surfaceLevels;

    protected Map() {
        mapData = new HashMap<Coordinate, Vector<PhysicalObject>>();
    }

    protected PhysicalObject[] getLocation(Coordinate location) {
        PhysicalObject[] objectsAtLocation = null;
        if (mapData.containsKey(location)) {
            objectsAtLocation = mapData.get(location).toArray(new PhysicalObject[mapData.get(location).size()]);
        }
        return objectsAtLocation;
    }

    protected int addItem(PhysicalObject item, Coordinate location) {
        int numItemsAtLocation = -1;
        if (mapData.containsKey(location)) {
            mapData.get(location).add(item);
            numItemsAtLocation = mapData.get(location).size();
        } else {
            Vector objectsAtLocation = new Vector<PhysicalObject>();
            objectsAtLocation.add(item);
            mapData.put(location, objectsAtLocation);
            numItemsAtLocation = 1;
        }

        return numItemsAtLocation;
    }

    protected boolean rmItem(int itemId, Coordinate location) {
        boolean foundItem = false;
        if (mapData.containsKey(location)) {
            int i = 0;
            for (PhysicalObject objectAtLocation : mapData.get(location)) {
                if (objectAtLocation.getObjectId() == itemId) {
                    mapData.get(location).remove(i);
                    foundItem = true;
                    break;
                }
                i++;
            }
        }
        return foundItem;
    }

    protected int mvItem(PhysicalObject item, Coordinate source, Coordinate destination) {
        int numCollidedItem = -1;
        if (rmItem(item.getObjectId(), source)) {
            numCollidedItem = addItem(item, destination);
        }
        return numCollidedItem;
    }

    protected Vector<Vector<PhysicalObject>> getObjectsInRadius(int radius, Coordinate location) {

        Vector<Vector<PhysicalObject>> objectVectors = new Vector<Vector<PhysicalObject>>();

        //This method returns 4 Vectors:
        Vector<PhysicalObject> objectsInSmellRadius = new Vector<PhysicalObject>();
        Vector<PhysicalObject> objectsInTalkRadius = new Vector<PhysicalObject>();
        Vector<PhysicalObject> objectsInSightRadius = new Vector<PhysicalObject>();
        Vector<PhysicalObject> objectsInCollisionRadius = new Vector<PhysicalObject>();

        //The values are not duplicated.  An ant is expected to know that if something is in
        //Sight Radius, well then it's obviously also in SmellRadius.

        //boolean inSmellRadiusX;
        //boolean inSmellRadiusY;
        boolean inTalkRadiusX;
        boolean inTalkRadiusY;
        boolean inSightRadiusX;
        boolean inSightRadiusY;
        boolean inCollisionRadiusX;
        boolean inCollisionRadiusY;

        Integer leftBound = location.getX() - radius;
        Integer rightBound = location.getX() + radius;
        Integer topBound = location.getY() + radius;
        Integer lowerBound = location.getY() - radius;

        for (Integer x = leftBound; x <= rightBound; x++) {
            for (Integer y = lowerBound; y <= topBound; y++) {
                //inSmellRadiusX = false;
                //inSmellRadiusY = false;
                inTalkRadiusX = false;
                inTalkRadiusY = false;
                inSightRadiusX = false;
                inSightRadiusY = false;
                inCollisionRadiusX = false;
                inCollisionRadiusY = false;
                Coordinate currentLocation = new Coordinate(x, y);
                if (mapData.containsKey(currentLocation)) {
                    if ((currentLocation.getX() >= (location.getX() - collisionRadius)) && (currentLocation.getX() <= (location.getX() + collisionRadius))) {
                        inCollisionRadiusX = true;
                        inSightRadiusX = true;
                        inTalkRadiusX = true;
                        //inSmellRadiusX = true;
                    } else if ((currentLocation.getX() >= (location.getX() - sightRadius)) && (currentLocation.getX() <= (location.getX() + sightRadius))) {
                        inSightRadiusX = true;
                        inTalkRadiusX = true;
                        //inSmellRadiusX = true;
                    } else if ((currentLocation.getX() >= (location.getX() - talkRadius)) && (currentLocation.getX() <= (location.getX() + talkRadius))) {
                        inTalkRadiusX = true;
                        inCollisionRadiusX = true;
                    } else {
                        inCollisionRadiusX = true;
                    }

                    if ((currentLocation.getY() >= (location.getY() - collisionRadius)) && (currentLocation.getY() <= (location.getY() + collisionRadius))) {
                        inCollisionRadiusY = true;
                        inSightRadiusY = true;
                        inTalkRadiusY = true;
                        //inSmellRadiusY = true;
                    } else if ((currentLocation.getY() >= (location.getY() - sightRadius)) && (currentLocation.getY() <= (location.getY() + sightRadius))) {
                        inSightRadiusY = true;
                        inTalkRadiusY = true;
                        //inSmellRadiusY = true;
                    } else if ((currentLocation.getY() >= (location.getY() - talkRadius)) && (currentLocation.getY() <= (location.getY() + talkRadius))) {
                        inTalkRadiusY = true;
                        inCollisionRadiusY = true;
                    } else {
                        inCollisionRadiusY = true;
                    }
                }

                for (PhysicalObject objectAtLocation : mapData.get(currentLocation)) {
                    if (inCollisionRadiusX && inCollisionRadiusY) {
                        objectsInCollisionRadius.add(objectAtLocation);
                    } else if (inSightRadiusX && inSightRadiusY) {
                        objectsInSightRadius.add(objectAtLocation);
                    } else if (inTalkRadiusX && inTalkRadiusY) {
                        objectsInTalkRadius.add(objectAtLocation);
                    } else {
                        objectsInSmellRadius.add(objectAtLocation);
                    }
                }
            }
        }
        objectVectors.add(objectsInCollisionRadius);
        objectVectors.add(objectsInSightRadius);
        objectVectors.add(objectsInTalkRadius);
        objectVectors.add(objectsInSmellRadius);

        return objectVectors;
    }

    public boolean loadImage(File imageFile) {
        boolean success = false;
        try {
            // Read from a file
            //surfaceLevels = ImageIO.read(imageFile);

            // Read from an input stream
            InputStream is = new BufferedInputStream(new FileInputStream(imageFile));
            surfaceLevels = ImageIO.read(is);
            success = true;
        } catch (IOException e) {
            surfaceLevels = null;

        }
        return success;
    }
}
